package helma.util;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;

import at.fpmedv.eclipse.helma.core.HelmaCorePlugin;
import at.fpmedv.eclipse.helma.logging.IEclipseHelmaLogger;

/**
 * We use this class to abuse the consoleLogger from helma.main.Server
 * it is a wrapper for the extensions written for logging
 * @author fpm
 *
 */
public class EclipseHelmaLoggerDistributor extends helma.util.Logger {

	/**
	 * The name of the extension point for loggers to register
	 */
	private static final String loggerExtentionId = "at.fpmedv.eclipse.helma.logging";
	
	/**
	 * list of loggers to notify for logging events
	 * @see EclipseHelmaLoggerDistributor#getLogger
	 */
	private List<IEclipseHelmaLogger> loggers;
	

	/**
	 * setting the helma.util.Logging.consoleLog to our distributor
	 * 
	 * @param force if true the helma.util.Logging.consoleLog is not checked to be null
	 */
	public static void setLogger(boolean force) {
		if (helma.util.Logging.consoleLog == null || force) {
			helma.util.Logging.consoleLog = new EclipseHelmaLoggerDistributor();
		}
		//org.eclipse.ui.internal.console.ConsoleView test = org.eclipse.ui.internal.console.ConsoleView();
	}

	/**
	 * just a getter for the loggers. Calls computeLoggers if loggers == null
	 * 
	 * @return list of loggers
	 */
	private List<IEclipseHelmaLogger> getLoggers() {
		if (loggers == null) {
			loggers = computeLogger();
		}
		return loggers;
	}
	
	/**
	 * Find all extensions that extend the xetension point and store them for
	 * later usage.
	 * 
	 * @return list of found extensions
	 */
	private List<IEclipseHelmaLogger> computeLogger() {
		IExtensionRegistry registry = Platform.getExtensionRegistry();
		IExtensionPoint extensionPoint = registry.getExtensionPoint(loggerExtentionId);
		IExtension[] extensions = extensionPoint.getExtensions();
		ArrayList<IEclipseHelmaLogger> result = new ArrayList<IEclipseHelmaLogger>();
		for (int i = 0; i < extensions.length; i++) {
			IConfigurationElement[] elements = extensions[i].getConfigurationElements();
			for (int j = 0; j < elements.length; j++) {
				try {
					IEclipseHelmaLogger logger = (IEclipseHelmaLogger) elements[j].createExecutableExtension("class");
					result.add(logger);
				} catch (CoreException e) {
					// do nothing
					HelmaCorePlugin.getDefault().log("logger not an IEclipseHelmaLogger", e);
				}
			}
		}
		return result;
	}

	public void debug(Object msg) {
		for (Iterator<IEclipseHelmaLogger> all = getLoggers().iterator(); all.hasNext(); ) {
			final IEclipseHelmaLogger each = all.next();
			each.debug(msg);
		}
	}

	public void debug(Object msg, Throwable t) {
		for (Iterator<IEclipseHelmaLogger> all = getLoggers().iterator(); all.hasNext(); ) {
			final IEclipseHelmaLogger each = all.next();
			each.debug(msg, t);
		}
	}

	public void error(Object msg) {
		for (Iterator<IEclipseHelmaLogger> all = getLoggers().iterator(); all.hasNext(); ) {
			final IEclipseHelmaLogger each = all.next();
			each.error(msg);
		}
	}

	public void error(Object msg, Throwable t) {
		for (Iterator<IEclipseHelmaLogger> all = getLoggers().iterator(); all.hasNext(); ) {
			final IEclipseHelmaLogger each = all.next();
			each.error(msg, t);
		}
	}

	public void fatal(Object msg) {
		for (Iterator<IEclipseHelmaLogger> all = getLoggers().iterator(); all.hasNext(); ) {
			final IEclipseHelmaLogger each = all.next();
			each.fatal(msg);
		}		
	}

	public void fatal(Object msg, Throwable t) {
		for (Iterator<IEclipseHelmaLogger> all = getLoggers().iterator(); all.hasNext(); ) {
			final IEclipseHelmaLogger each = all.next();
			each.fatal(msg, t);
		}
	}

	public void info(Object msg) {
		for (Iterator<IEclipseHelmaLogger> all = getLoggers().iterator(); all.hasNext(); ) {
			final IEclipseHelmaLogger each = all.next();
			each.info(msg);
		}		
	}

	public void info(Object msg, Throwable t) {
		for (Iterator<IEclipseHelmaLogger> all = getLoggers().iterator(); all.hasNext(); ) {
			final IEclipseHelmaLogger each = all.next();
			each.info(msg, t);
		}
	}
	
	public void trace(Object msg) {
		for (Iterator<IEclipseHelmaLogger> all = getLoggers().iterator(); all.hasNext(); ) {
			final IEclipseHelmaLogger each = all.next();
			each.trace(msg);
		}		
	}
	
	public void trace(Object msg, Throwable t) {
		for (Iterator<IEclipseHelmaLogger> all = getLoggers().iterator(); all.hasNext(); ) {
			final IEclipseHelmaLogger each = all.next();
			each.trace(msg, t);
		}
	}

	public void warn(Object msg) {
		for (Iterator<IEclipseHelmaLogger> all = getLoggers().iterator(); all.hasNext(); ) {
			final IEclipseHelmaLogger each = all.next();
			each.warn(msg);
		}		
	}

	/**
	 * passes warn msg and t to all Extentions
	 */
	public void warn(Object msg, Throwable t) {
		for (Iterator<IEclipseHelmaLogger> all = getLoggers().iterator(); all.hasNext(); ) {
			final IEclipseHelmaLogger each = all.next();
			each.warn(msg, t);
		}
	}
	
	/**
	 * always returns true because the individual loggers should handle this separately
	 */
	public boolean isDebugEnabled() {
		return true;
	}

	/**
	 * always returns true because the individual loggers should handle this separately
	 */
	public boolean isErrorEnabled() {
		return true;
	}

	/**
	 * always returns true because the individual loggers should handle this separately
	 */
	public boolean isFatalEnabled() {
		return true;
	}

	/**
	 * always returns true because the individual loggers should handle this separately
	 */
	public boolean isInfoEnabled() {
		return true;
	}

	/**
	 * always returns true because the individual loggers should handle this separately
	 */
	public boolean isTraceEnabled() {
		return true;
	}

	/**
	 * always returns true because the individual loggers should handle this separately
	 */
	public boolean isWarnEnabled() {
		return true;
	}
}
